﻿namespace Reals.Parellel
{
  #region Using directives

  using System;
  using System.Collections.Generic;
  using System.Text;
  using System.Threading;

  #endregion

  /// <summary>
  /// 微过程时序线.
  /// </summary>
  public interface MicroThread : MicroCycling
  {
    /// <summary>
    /// 获取或者设置两个
    /// 嘀哒之间的实际时间
    /// 间隔,单位将由具体
    /// 实现决定.
    /// </summary>
    int SpinIteration { get;set;}
    /// <summary>
    /// 获取当前运行状态.
    /// </summary>
    /// <value>当前运行状态.</value>
    bool Running { get;}
    /// <summary>
    /// 启动时序引擎.
    /// </summary>
    void Start();
    /// <summary>
    /// 终止时序引擎.
    /// </summary>
    void Terminate();
  }

  /// <summary>
  /// 微过程时序线的实现.
  /// </summary>
  public class MicroThreadImpl : MicroCyclingImpl, MicroThread
  {
    #region Shortcuts
    public new static MicroThread it()
    {
      return new MicroThreadImpl();
    }
    #endregion
    #region Fields
    protected bool allowRunning = false;
    protected bool currentRunning = false;
    protected int iteration = 0x1000000;
    protected ThreadPriority priority = ThreadPriority.Normal;
    #endregion
    #region Properties
    public virtual bool Running
    {
      get { return this.currentRunning; }
    }
    public virtual int SpinIteration
    {
      get { return this.iteration; }
      set { this.iteration = value; }
    }

    public virtual ThreadPriority EngineThreadPriority
    {
      get
      {
        return this.priority;
      }
      set
      {
        this.priority = value;
      }
    }

    #endregion
    #region Constructors
    public MicroThreadImpl() { }
    public MicroThreadImpl(int iteration) : this(iteration, ThreadPriority.Normal) { }
    public MicroThreadImpl(int iteration, ThreadPriority priority) { this.iteration = iteration; this.priority = priority; }

    ~MicroThreadImpl()
    {
      this.Dispose();
    }
    #endregion
    #region Methods
    public virtual void Start()
    {
      if (!this.allowRunning)
      {
        this.allowRunning = ThreadPool.QueueUserWorkItem(new WaitCallback(this.ThreadEntry), this);
      }
      while (!this.currentRunning)
      {
        Thread.Sleep(0);
      }
    }

    public virtual void Terminate()
    {
      if (this.currentRunning)
      {
        this.allowRunning = false;
      }
      while (this.currentRunning)
      {
        Thread.Sleep(0);
      }
    }

    public override void Dispose()
    {
      this.Terminate();

      base.Dispose();
    }
    protected virtual void ThreadEntry(object anything)
    {

      Thread.CurrentThread.Priority
          = this.EngineThreadPriority;

      this.ThreadCore();
    }

    protected virtual void ThreadCore()
    {
      this.currentRunning = true;
      do
      {
        if (this.EntryProcess != null)
        {
          this.EntryProcess();
        }
        this.SpinAfterCurrentLayer();
      } while (this.allowRunning);

      this.currentRunning = false;
    }

    protected virtual void SpinAfterCurrentLayer()
    {
      Thread.SpinWait(this.SpinIteration);
    }
    #endregion
  }
}
